package cn.livenovel.thirddata.configuration;

import java.io.IOException;
import java.sql.SQLException;

import javax.sql.DataSource;

import org.apache.commons.lang3.ArrayUtils;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import com.alibaba.druid.pool.DruidDataSource;

/**
 * 数据源配置
 * 
 * @author shaohui
 * @date 2017-06-14 15:36:36
 */
@Configuration
public class DataSourceConfiguration {
    /**
     * 默认初始连接数
     */
    public static final int DEFAULT_SQL_DATASOURCE_INITIAL_SIZE = 10;
    
    /**
     * 默认最小空闲连接数
     */
    public static final int DEFAULT_SQL_DATASOURCE_MIN_IDLE = 10;
    
    /**
     * 默认最大活动连接数
     */
    public static final int DEFAULT_SQL_DATASOURCE_MAX_ACTIVE = 50;
    
    /**
     * 默认连接超时时间
     */
    public static final long DEFAULT_SQL_DATASOURCE_MAX_WAIT = 10 * 1000;
    
    /**
     * 默认多久（ms）检测需要关闭的空闲连接
     */
    public static final long DEFAULT_SQL_DATASOURCE_TIME_BETWEEN_EVICTION_RUNS_MILLIS = 10 * 1000;
    
    /**
     * 连接在池中默认最小生存时间
     */
    public static final long DEFAULT_SQL_DATASOURCE_MIN_EVICTABLE_IDLE_TIME_MILLIS = 10 * 1000;
    
    /**
     * 用来检测连接是否有效的默认sql
     */
    public static final String DEFAULT_SQL_DATASOURCE_VALIDATION_QUERY = "SELECT 'a'";
    
    /**
     * 是否检测空闲连接有效
     */
    public static final boolean DEFAULT_SQL_DATASOURCE_TEST_WHILE_IDLE = true;
    
    /**
     * 获取连接时是否检测连接有效
     */
    public static final boolean DEFAULT_SQL_DATASOURCE_TEST_ON_BORROW = false;
    
    /**
     * 归还连接时是否检测连接有效
     */
    public static final boolean DEFAULT_SQL_DATASOURCE_TEST_ON_RETURN = false;
    
    /**
     * 是否开启pscache
     */
    public static final boolean DEFAULT_SQL_DATASOURCE_POOL_PREPARED_STATEMENTS = false;
    
    /**
     * 开启pscache后每个连接上cache大小
     */
    public static final int DEFAULT_SQL_DATASOURCE_MAX_POOL_PREPARED_STATEMENT_PER_CONNECTION_SIZE = 20;

    /**
     * 
     * 配置数据库连接池 <br/> 
     * 
     * @return
     *
     * @author shaohui
     * @date 2017年4月2日下午8:35:52
     * @since JDK 1.8
     */
    @Bean
    public DataSource dataSource(Environment env) {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(env.getRequiredProperty("datasource.url"));
        dataSource.setUsername(env.getRequiredProperty("datasource.username"));
        dataSource.setPassword(env.getRequiredProperty("datasource.password"));
        dataSource.setInitialSize(env.getProperty("datasource.initialSize", Integer.class, DEFAULT_SQL_DATASOURCE_INITIAL_SIZE));
        dataSource.setMinIdle(env.getProperty("datasource.minIdle", Integer.class, DEFAULT_SQL_DATASOURCE_MIN_IDLE));
        dataSource.setMaxActive(env.getProperty("datasource.maxActive", Integer.class, DEFAULT_SQL_DATASOURCE_MAX_ACTIVE));
        dataSource.setMaxWait(env.getProperty("datasource.maxWait", Long.class, DEFAULT_SQL_DATASOURCE_MAX_WAIT));
        dataSource.setTimeBetweenEvictionRunsMillis(env.getProperty("datasource.timeBetweenEvictionRunsMillis", Long.class, DEFAULT_SQL_DATASOURCE_MIN_EVICTABLE_IDLE_TIME_MILLIS));
        dataSource.setValidationQuery(env.getProperty("datasource.validationQuery", DEFAULT_SQL_DATASOURCE_VALIDATION_QUERY));
        dataSource.setTestWhileIdle(env.getProperty("datasource.testWhileIdle", Boolean.class, DEFAULT_SQL_DATASOURCE_TEST_WHILE_IDLE));
        dataSource.setTestOnBorrow(env.getProperty("datasourc e.testOnBorrow", Boolean.class, DEFAULT_SQL_DATASOURCE_TEST_ON_BORROW));
        dataSource.setTestOnReturn(env.getProperty("datasource.testOnReturn", Boolean.class, DEFAULT_SQL_DATASOURCE_TEST_ON_RETURN));
        dataSource.setPoolPreparedStatements(env.getProperty("datesource.poolPreparedStatements", Boolean.class, DEFAULT_SQL_DATASOURCE_POOL_PREPARED_STATEMENTS));
        dataSource.setMaxPoolPreparedStatementPerConnectionSize(env.getProperty("datesource.maxPoolPreparedStatementPerConnectionSize", Integer.class, DEFAULT_SQL_DATASOURCE_MAX_POOL_PREPARED_STATEMENT_PER_CONNECTION_SIZE));
        dataSource.setPoolPreparedStatements(false);
        try {
            dataSource.setFilters("stat");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return dataSource;
    }
    
    /**
     * 
     * 配置事务管理器 <br/> 
     * 
     *
     * @author shaohui
     * @date 2017年4月2日下午8:36:45
     * @since JDK 1.8
     */
    @Bean
    public PlatformTransactionManager bookTransactionManager(@Autowired DataSource dataSource) {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }
    
    @Bean
    public SqlSessionFactoryBean bookSqlSession(@Autowired DataSource dataSource) throws IOException {
        SqlSessionFactoryBean sqlSession = new SqlSessionFactoryBean();
        sqlSession.setDataSource(dataSource);
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sqlSession.setMapperLocations(ArrayUtils.addAll(resolver.getResources("/mapper/*.xml")));
        return sqlSession;
    }
    
    @Bean
    public MapperScannerConfigurer bookMapperScannerConfigurer() {
        MapperScannerConfigurer mapperScanner = new MapperScannerConfigurer();
        mapperScanner.setBasePackage("cn.livenovel.thirddata.dao");
        return mapperScanner;
    }
}
